package com.ls.designModel;

import sun.misc.Unsafe;

import javax.imageio.IIOException;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * 单例设计模式
 */
public class Single {

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException, NoSuchFieldException {
//        // 测试是否是饿汉式，一使用类就构造
//        HungerSingle.otherMethod(); //先输出 HungerSingle constructor 再 otherMethod...说明是饿汉式
//        HungerSingle instance = HungerSingle.getInstance(); // com.ls.designModel.HungerSingle@2437c6dc
//        HungerSingle instance2 = HungerSingle.getInstance(); // com.ls.designModel.HungerSingle@2437c6dc
//        System.out.println(instance);
//        System.out.println(instance2);
//        // 反射破坏单例
////        reflection(HungerSingle.class);
//        // 反序列化破话单例
////        serializable(instance);
//        unsafe(HungerSingle.class);


//        // 枚举实现单例
//        EnumSingle instance = EnumSingle.getInstance();
//        EnumSingle instance1 = EnumSingle.getInstance();
//        System.out.println(instance);
//        System.out.println(instance1);


//        LazySingle instance = LazySingle.getInstance();
//        LazySingle instance1 = LazySingle.getInstance();
//        System.out.println(instance);
//        System.out.println(instance);
//        reflection(LazySingle.class);

//        Thread t1 = new Thread(() -> {
//            LazySingle instance = LazySingle.getInstance();
//            System.out.println("线程1"+instance);
//        }, "t1");
//
//        Thread t2 = new Thread(() -> {
//            LazySingle instance = LazySingle.getInstance();
//            System.out.println("线程2"+instance);
//        }, "t2");
//
//        t1.start();
//        t2.start();

        InnerSingle instance = InnerSingle.getInstance();
        InnerSingle instance1 = InnerSingle.getInstance();

        System.out.println(instance);
        System.out.println(instance1);


    }

    /**
     * 反射破坏单例
     */
    public static void reflection(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        // 设置可访问
        constructor.setAccessible(true);
        Object o = constructor.newInstance();
        System.out.println(o.toString());
    }

    /**
     * 反序列化破坏单例
     * @param instance
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void serializable(Object instance) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos =  new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(instance);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        System.out.println("反序列化创建实例"+ois.readObject());
    }

    public static void unsafe(Class<?> clazz) throws InstantiationException, NoSuchFieldException, IllegalAccessException {
        Object o = getUnsafeInstance().allocateInstance(clazz);
        System.out.println("通过unsafe获得"+o);
    }

    private static Unsafe getUnsafeInstance() throws SecurityException,
            NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException {
        Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafeInstance.setAccessible(true);
        return (Unsafe) theUnsafeInstance.get(Unsafe.class);
    }



}
